Dynamicke pole 2.

Otázka od: David Lebeda

5. 11. 2004 15:46

Ahoj,

stale se nemohu zbavit problemu s dealokaci dynamickeho pole.

Mam tyto deklarace.

TRec = packed record
 Index: integer;
 Nazev: string;
 Popis: string;
end;

TPole = packed array of TRec;

V programu Vytvorim MemoryStream a naplnim jej daty ze zdroje dat. MemoryStream
pak obsahuje za sebou naskladane takoveto reocrdy:

TRec1 = packed record
 Index: integer;
 Nazev: string[30];
 Popis: string[50];
end;

Ja cely Memory stream prolezu a naplnim z nej dynamickou promennou typu TPole.
V cyklu pekne priradim Index do Indexu, Nazev do Nazvu, Popis do Popisu.
Nasledne se memory stream uvolni. Vysledkem je, ze velikost zabrane pameti je
pak daleko mensi nez byla delka memory streamu, protoze ansistringy se
naalokuji jen v delce odpovidajici skutecnemu obsahu retezcu (jen malo retezcu
ma delku 30 resp. 50 znaku), takze budovat TPole z TRec1 misto z TRec by bylo
znacne plytvani.

Na konci programu delam to, ze cele to dynamicke pole projedu
for i := 0 to high(Pole) do
begin
 Pole[i].Nazev := '';
 Pole[i].Popis := '';
end;
SetLength(Pole, 0); //dealokace

I presto nekdy, zridka a nepravidelne, v prubehu vyse uvedeneho cyklu vznikne
Invalid pointer operation. Uz opravdu nevim, kde by mohla byt chyba. Jedine, co
me jeste napada, je misto ansistringu pouzit v TRec PChar a pri plneni vzdy
volat StrAlloc. Nebo tam nekde chyba je?

David Lebeda

Odpovedá: Ing. Petr Sikola

5. 11. 2004 15:52

ja bych pro zacatek pouzil
  for i := Low(Pole) to high(Pole) do
treba to pomuze  

> for i := 0 to high(Pole) do
> begin
> Pole[i].Nazev := '';
> Pole[i].Popis := '';
> end;


Petr Sikola



Odpovedá: Karel Kral

5. 11. 2004 16:28

A zkusil jsi zavolat na kazdy record Finalize?
David Lebeda napsal(a):
> Ahoj,

>
> Na konci programu delam to, ze cele to dynamicke pole projedu
> for i := 0 to high(Pole) do
> begin
> Pole[i].Nazev := '';
> Pole[i].Popis := '';
> end;
> SetLength(Pole, 0); //dealokace
>
> I presto nekdy, zridka a nepravidelne, v prubehu vyse uvedeneho cyklu vznikne
> Invalid pointer operation. Uz opravdu nevim, kde by mohla byt chyba. Jedine,
co me jeste napada, je misto ansistringu pouzit v TRec PChar a pri plneni vzdy
volat StrAlloc. Nebo tam nekde chyba je?
>
> David Lebeda
>
>


--
______________________________________________________
Karel Kral, vedouci odd. IT / IT manager
Purus, s.r.o., Cezavy 627, 664 56 Blucina, CZ
Tel: 547 235 000, 602 552 432, Fax: 547 231 203
E-Mail: mailto:kral@purus.cz, WWW: http://www.purus.cz
______________________________________________________


Odpovedá: delphin@post.cz

5. 11. 2004 16:38

> TRec = packed record
> Index: integer;
> Nazev: string;
> Popis: string;
> end;
>
> TPole = packed array of TRec;

Dynamicke pole lze jednoduse cele dealokovat pomoci Pole:=nil; Delphi
samo zajisti korektni uvolneni stringu z pole.

Invalid pointer operation pri uvolnovani muze zpusobit bud chybny index pri
predchozi praci s polem nebo libovolna jina chybna i zdanlive nesouvisejici
prace s pameti.


Odpovedá: David Lebeda

8. 11. 2004 8:39

> > TRec = packed record
> > Index: integer;
> > Nazev: string;
> > Popis: string;
> > end;
> >
> > TPole = packed array of TRec;
>
> Dynamicke pole lze jednoduse cele dealokovat pomoci Pole:=nil; Delphi
> samo zajisti korektni uvolneni stringu z pole.

Ahoj,

prapuvodne jsem delal nejprve pouze Pole := nil; Pritom zacalo vznikat prave
(obcas, nahodile) Invalid pointer operation. Druhy krok byl jeste pred
vynilovanim volat Finalize(Pole); To spadlo tusim pokazde, zjevne to nebyl
dobry krok. Volani Finalize v cyklu pro vsechny prvky pole jsem taky zkousel a
chyba rovnez nezmizela. On je problem v tom, ze to nekdy i pomerne dlouhou dobu
bezi a pak teprve vznikne vyjimka - a zas je nejakou dobu pokoj. Proto jsem v
patek zacal provadet logovani do souboru, abych zjistil, kdy problem nastava.

> Invalid pointer operation pri uvolnovani muze zpusobit bud chybny index pri
> predchozi praci s polem nebo libovolna jina chybna i zdanlive nesouvisejici
> prace s pameti.

Pouzil jsem Exception dialog z JCL. Chyba nastava obvykle kolem dvoutisiciho
zaznamu (plus minus 200), pole ma 107000 prvku, nejde tedy o problem s chybnou
indexaci na okraji pole, Exception dialog hlasi, ze chyba vznika na volani
FreeMem v _LStrClr (tusim, za nazev z hlavy presne nerucim), coz je procedura v
unite system a podle nazvu soudim, ze ma uvolnit string z pameti.

David Lebeda

Odpovedá: Petr Fejfar

8. 11. 2004 11:38

David Lebeda wrote:

> hlasi, ze chyba vznika na volani FreeMem v _LStrClr (tusim, za nazev

Zajimavejsi je call stack tj. v jakem kontextu se to vola.

pf


Odpovedá: delphin@post.cz

8. 11. 2004 10:45

> Pouzil jsem Exception dialog z JCL. Chyba nastava obvykle kolem
dvoutisiciho zaznamu (plus minus 200), pole ma 107000 prvku, nejde tedy o
problem s chybnou indexaci na okraji pole, Exception dialog hlasi, ze chyba
vznika na volani FreeMem v _LStrClr (tusim, za nazev z hlavy presne
nerucim), coz je procedura v unite system a podle nazvu soudim, ze ma
uvolnit string z pameti.


Neni nic jednodussiho, nez si to vyzkouset v novem projektu. Predpokladam,
ze nasledujici kod bude fungovat na 100%.

SetLength(Pole,107000);
for i:=low(Pole) to high(Pole) do
begin
 Pole[i].Nazev:=inttostr(i);
 Pole[i].Popis:=inttostr(i);
end;

Pole:=nil;